package com.vanzo.instruction;

import android.content.Intent;
import android.os.UserHandle;
import android.provider.Settings;

import com.vanzo.Tpplication;
import com.vanzo.util.LogUtil;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android_serialport_api.SerialPort;

/**
 * Created by tisen on 2018/3/1.
 */

public class Instruction {
    public static final String DEVICE_PATH = "/dev/ttyMT0";
    public static final int BAUD_RATE = 9600;

    private Tpplication tpplication;
    private SerialPort serialPort;
    private OutputStream outputStream;
    private InputStream inputStream;
    private ReadThread readThread;

    private boolean prepare = false;
    private boolean connect = false;


    public Instruction(Tpplication tpplication) {
        this.tpplication = tpplication;
        try {
            init();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void init() throws IOException {
        serialPort = new SerialPort(new File(DEVICE_PATH), BAUD_RATE, 0);
        outputStream = serialPort.getOutputStream();
        inputStream = serialPort.getInputStream();
        prepare = true;
    }


    private OnResultListener listener;
    private Console console;
    private Prepare prepareCallback;

    public void setListener(OnResultListener listener) {
        this.listener = listener;
    }

    public void setConsole(Console console) {
        this.console = console;
    }

    public void sendInstruction(String ins) {
        LogUtil.put(this, "sendInstruction = " + ins, LogUtil.WARN);
        if (!prepare)
            return;
        if (console != null) {
            console.onConsole(ins);
        }
        int i;
        CharSequence t = ins + "\r";
        char[] text = new char[t.length()];
        for (i = 0; i < t.length(); i++) {
            text[i] = t.charAt(i);
        }
        try {
            outputStream.write(new String(text).getBytes());
            outputStream.write('\n');
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }

    private boolean interrupt = true;

    private class ReadThread extends Thread {

        @Override
        public void run() {
            super.run();
            while (!interrupt) {
                LogUtil.put(this, "is not interrupt", LogUtil.WARN);
                int size = 0;
                try {
                    byte[] buffer = new byte[1024];
                    if (inputStream == null) return;
                    size = inputStream.read(buffer);
                    if (size > 0) {
                        onDataReceived(buffer, size);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    return;
                }
            }
        }
    }

    private StringBuilder temp = new StringBuilder();

    private void onDataReceived(final byte[] buffer, int size) {
        temp.append(new String(buffer, 0, size));
        if (temp.toString().endsWith("\r\n")) {
            LogUtil.put(this, "onDataReceived = " + temp.toString().trim(), LogUtil.WARN);
            if (listener != null) {
                listener.onResult(temp.toString());
            }
            if (console != null) {
                console.onConsole(temp.toString().trim());
            }
            if (temp.toString().contains(AT.POWER_STATUS) && prepareCallback != null) {
                prepareCallback.onPrepare(temp.toString().trim());
            }
            if (temp.toString().contains(AT.CONNECT_0)) {
                connect = true;
            }
            if (temp.toString().contains(AT.DISCONNECT_0)) {
                connect = false;
            }
            temp = new StringBuilder();
        } else {

        }
    }

    public void connect() {
        sendInstruction(AT.DMO_CONNECT);
    }

    public void disconnect() {
        sendInstruction(AT.DMO_DISCONNECT);
    }

    public void switchChannel(int channel, String tfreq, String rfreq) {
        sendInstruction(AT.DMO_CH_SWITCH + "=" + channel);
        sendInstruction(AT.DMO_SET_CHFREQ + "=" + tfreq + "," + rfreq);
    }

    public void powerLevel(int level) {
        sendInstruction(AT.DMO_SET_PWRSAVELV + "=" + level);
    }

    public void setSpkVolume(int volume) {
        sendInstruction(AT.DMO_SET_VOLUME + "=" + volume);
    }

    public void setMicVolume(int volume) {
        sendInstruction(AT.DMO_SETMIC + "+" + volume);
    }

    public void getVersion(OnResultListener listener) {
        this.listener = listener;
        sendInstruction(AT.DMO_VERSION);
    }

    public void pttDown() {
        sendInstruction(AT.DMO_PTT + "=1");
    }

    public void pttUp() {
        sendInstruction(AT.DMO_PTT + "=0");
    }

    public void sendBinary(String binary, OnResultListener listener) {
        this.listener = listener;
        sendInstruction(AT.DMO_BINARY);
    }

    public void start() {
        if (readThread == null) {
            readThread = new ReadThread();
        }
        readThread.start();
        interrupt = false;
        LogUtil.put(this, "read thread start", LogUtil.WARN);
    }

    private boolean isInterrupt;

    public void reStart() {
        if (readThread.isInterrupted()) {
            LogUtil.put(this, "read thread restart", LogUtil.WARN);
        } else {
            LogUtil.put(this, "read thread is not interrupt", LogUtil.WARN);
        }
        interrupt = false;
        readThread.start();
    }

    public void start(Prepare prepare) {
        this.prepareCallback = prepare;
        start();
    }

    public void interrupt() {
        if (readThread != null && !readThread.isInterrupted()) {
            readThread.interrupt();
            LogUtil.put(this, "read thread interrupt", LogUtil.WARN);
//            throw  new ReadThreadInterruptException();
        }
        interrupt = true;
    }

    public boolean isPower() {
        return TalkiePower.status();
    }

    public void setPower(boolean power) {
        LogUtil.put(this, "talkie power " + (power ? "on" : "off"), LogUtil.WARN);
        if (power) {
            TalkiePower.on();
        } else {
            TalkiePower.off();
        }
//        tpplication.sendBroadcast(new Intent("com.vanzo.talkie.POWER_CHANGE"),null);
    }



    public void setChannel(int channel, String tfreq, String rfreq, int powerlevel, int micVolume, int spkVolume) {
        switchChannel(channel, tfreq, rfreq);
        powerLevel(powerlevel);
        setMicVolume(micVolume);
        setSpkVolume(spkVolume);
    }


    public interface OnResultListener {
        void onResult(String result);
    }

    public interface Console {
        void onConsole(String result);
    }

    public interface Prepare {
        void onPrepare(String result);
    }
}
